﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ST.Common.Data;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Buz.Base;
using ST.Buz.Base.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Caching.Memory;
using ST.WX.Common;
using ST.WX.Common.Enums;
using ST.Common.Util.Mvc;
using ST.Buz.Base.ViewModel;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace ST.Buz.Service
{
	public partial interface IServiceWXAppConfig
	{
		/// <summary>
		/// 从缓存中读取应用配置信息，如果缓存里没有则从数据库中读取并写入到缓存
		/// </summary>
		/// <param name="appID"></param>
		/// <returns></returns>
		WX_AppConfig LoadOrGet(string appID);

		/// <summary>
		/// 获取默认应用配置
		/// </summary>
		/// <param name="appType"></param>
		/// <returns></returns>
		WX_AppConfig LoadOrGetDefault(int appType);

		/// <summary>
		/// 获取默认应用配置
		/// </summary>
		/// <param name="appType"></param>
		/// <returns></returns>
		WX_AppConfig LoadOrGetDefault(WXAppType appType);

		/// <summary>
		/// 分页列表
		/// </summary>
		PageData GetPageList(VMS_WX_AppConfig searchModel, UserSession sessionCurrent);

		/// <summary>
		/// 新增或修改信息
		/// </summary>
		int AddOrUpdate(WX_AppConfig model, UserSession sessionCurrent);

		/// <summary>
		/// 删除
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		bool Delete(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取查看时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		WX_AppConfig GetViewDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取编辑时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		WX_AppConfig GetEditDetail(int id, UserSession sessionCurrent);

		/// <summary>
		/// 获取下拉列表
		/// </summary>
		/// <returns></returns>
		List<WX_AppConfig> GetAllList(UserSession sessionCurrent);
	}

	public partial class ServiceWXAppConfig
	{
		private readonly IMemoryCache cache;
		private readonly string APP_CONFIG_CACHE_KEY_PREFIX = "WXAPP_";
		private readonly IServiceSysLog serviceSysLog;

		public ServiceWXAppConfig(BuzContext ctx,
			IServiceSysLog _serviceSysLog,
			IMemoryCache _cache,
			ILogger<ServiceWXAppConfig> log)
		{
			serviceSysLog = _serviceSysLog;

			context = ctx;
			logger = log;

			cache = _cache;
		}

		/// <summary>
		/// 从缓存中读取应用配置信息，如果缓存里没有则从数据库中读取并写入到缓存
		/// </summary>
		/// <param name="appID"></param>
		/// <returns></returns>
		public WX_AppConfig LoadOrGet(string appID)
		{
			WX_AppConfig model = null;
			try
			{
				if (string.IsNullOrEmpty(appID))
				{
					throw new ArgumentException("appid不能为空");
				}
				string cacheKey = APP_CONFIG_CACHE_KEY_PREFIX + appID;
				if (cache != null)
				{
					model = cache.Get(cacheKey) as WX_AppConfig;
				}
				if (model == null)
				{
					model = context.WXAppConfig.SingleOrDefault(m => m.AppID == appID);
				}
				if (model == null)
				{
					throw new EntityNotFoundException("未找到appid为" + appID + "的应用配置信息");
				}
				if (cache != null)
				{
					cache.Set(cacheKey, model);
					//MemoryCacheEntryOptions opts = new MemoryCacheEntryOptions();
					//opts.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(ret.expires_in);
					//opts.AbsoluteExpiration = DateTime.SpecifyKind(DateTime.Now.AddSeconds(ret.expires_in), DateTimeKind.Local);//微信官方7200秒过期
					//cache.Set(cacheKey, model, opts);
				}
				return model;
			}
			catch (ArgumentException ex)
			{
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			catch (EntityNotFoundException ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取应用配置信息出错");
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取应用配置信息出错");
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 获取默认应用配置（小程序、公众号只能有一条记录）
		/// </summary>
		/// <param name="appType"></param>
		/// <returns></returns>
		public WX_AppConfig LoadOrGetDefault(WXAppType appType)
		{
			return LoadOrGetDefault((int)appType);
		}

		/// <summary>
		/// 获取默认应用配置（小程序、公众号只能有一条记录）
		/// </summary>
		/// <param name="appType"></param>
		/// <returns></returns>
		public WX_AppConfig LoadOrGetDefault(int appType)
		{
			WX_AppConfig model = null;
			try
			{
				string cacheKey = APP_CONFIG_CACHE_KEY_PREFIX + "DEF_" + appType;
				if (cache != null)
				{
					model = cache.Get(cacheKey) as WX_AppConfig;
				}
				if (model == null)
				{
					model = context.WXAppConfig.SingleOrDefault(m => m.AppType == appType);
				}
				if (model == null)
				{
					throw new EntityNotFoundException("未找到类型为" + appType + "的默认应用配置信息");
				}
				if (cache != null)
				{
					cache.Set(cacheKey, model);
					//MemoryCacheEntryOptions opts = new MemoryCacheEntryOptions();
					//opts.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(ret.expires_in);
					//opts.AbsoluteExpiration = DateTime.SpecifyKind(DateTime.Now.AddSeconds(ret.expires_in), DateTimeKind.Local);//微信官方7200秒过期
					//cache.Set(cacheKey, model, opts);
				}
				return model;
			}
			catch (ArgumentException ex)
			{
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			catch (EntityNotFoundException ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取应用配置信息出错");
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取应用配置信息出错");
				throw new WXException("获取应用配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 分页列表
		/// </summary>
		public PageData GetPageList(VMS_WX_AppConfig searchModel, UserSession sessionCurrent)
		{
			PageData result = null;
			try
			{
				searchModel.Validate();

				var query = (from m in context.WXAppConfig
							 select new
							 {
								 m.AppID,
								 m.ID,
								 m.AppType,
								 m.AppName,
								 m.AppDesc,
								 m.AddDate,
								 m.AddManName,
								 m.OrgID,
								 m.AddManID,
								 m.Domain,
								 m.SvrIP,
								 m.MchID,
								 m.Sort
							 }).AsNoTracking();
				if (!string.IsNullOrEmpty(searchModel.appname))
				{
					query = query.Where(m => EF.Functions.Like(m.AppName, "%" + searchModel.appname + "%"));
				}
				if (!string.IsNullOrEmpty(searchModel.appid))
				{
					query = query.Where(m => m.AppID == searchModel.appid);
				}
				//if (searchModel.ids != null && searchModel.ids.Length > 0)
				//{
				//	query = query.Where(m => searchModel.ids.Contains(m.ID));
				//}
				if (searchModel.apptype.HasValue && searchModel.apptype.Value > 0)
				{
					query = query.Where(m => m.AppType == searchModel.apptype.Value);
				}
				if (searchModel.orgids != null && searchModel.orgids.Length > 0)
				{
					query = searchModel.orgids.Length == 1 ? query.Where(m => m.OrgID == searchModel.orgids[0]) : query.Where(m => searchModel.orgids.Contains(m.OrgID));
				}
				switch (searchModel.sortby)
				{
					default:
						query = query.OrderByDescending(e => e.ID);
						break;
				}
				result = new PageData(searchModel.pnum.Value, searchModel.psize.Value);
				result.Load(query);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取分页数据出错");
				throw new BuzException("获取分页数据失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return result;
		}

		/// <summary>
		/// 新增或修改信息
		/// </summary>
		public int AddOrUpdate(WX_AppConfig model, UserSession sessionCurrent)
		{
			try
			{
				if (model == null)
				{
					throw new BuzException("参数不能为空");
				}
				if (model.ID > 0)
				{
					var modelOld = (from m in context.WXAppConfig
									where m.ID == model.ID
									select m).SingleOrDefault();
					if (modelOld.AppID != model.AppID)
					{
						if (context.WXAppConfig.Any(x => x.AppID == model.AppID && x.ID != model.ID))
						{
							throw new BuzException("已存在相同ID的应用");
						}
					}
					if (!string.IsNullOrEmpty(model.AppSecret) && model.AppSecret.Trim('*').Length > 0)
					{
						modelOld.AppSecret = model.AppSecret.Trim('*');
					}
					if (!string.IsNullOrEmpty(model.AppToken) && model.AppToken.Trim('*').Length > 0)
					{
						modelOld.AppToken = model.AppToken.Trim('*');
					}
					if (!string.IsNullOrEmpty(model.EncodingAESKey) && model.EncodingAESKey.Trim('*').Length > 0)
					{
						modelOld.EncodingAESKey = model.EncodingAESKey.Trim('*');
					}
					if (!string.IsNullOrEmpty(model.MchKey) && model.MchKey.Trim('*').Length > 0)
					{
						modelOld.MchKey = model.MchKey.Trim('*');
					}
					modelOld.AppID = model.AppID;
					modelOld.AppName = model.AppName;
					modelOld.AppDesc = model.AppDesc;
					modelOld.AppType = model.AppType;
					modelOld.SvrIP = model.SvrIP;
					modelOld.Domain = model.Domain;
					modelOld.Sort = model.Sort;
					modelOld.MchID = model.MchID;
					modelOld.NotifyUrl = model.NotifyUrl;
					context.SaveChanges();
				}
				else
				{
					if (context.WXAppConfig.Any(x => x.AppID == model.AppID))
					{
						throw new BuzException("已存在相同ID的应用");
					}
					model.AddDate = DateTime.Now;
					model.AddManID = sessionCurrent.UserID;
					model.AddManName = sessionCurrent.UserName;
					model.OrgID = sessionCurrent.OrgID;

					model.ID = Add(model);
				}
				return model.ID;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (DbUpdateException ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
				throw new BuzException("数据库保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
				throw new BuzException("保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}


		/// <summary>
		/// 获取查看时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public WX_AppConfig GetViewDetail(int id, UserSession sessionCurrent)
		{
			return GetEditDetail(id, sessionCurrent);
		}

		/// <summary>
		/// 获取编辑时的详细信息
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public WX_AppConfig GetEditDetail(int id, UserSession sessionCurrent)
		{
			try
			{
				var result = (from m in context.WXAppConfig
							  where m.ID == id
							  select new WX_AppConfig()
							  {
								  ID = m.ID,
								  AppID = m.AppID,
								  AppName = m.AppName,
								  AppDesc = m.AppDesc,
								  AppSecret = !string.IsNullOrEmpty(m.AppSecret) ? "***" : "",
								  AppToken = !string.IsNullOrEmpty(m.AppToken) ? "***" : "",
								  EncodingAESKey = !string.IsNullOrEmpty(m.EncodingAESKey) ? "***" : "",
								  MchKey = !string.IsNullOrEmpty(m.MchKey) ? "***" : "",
								  AppType = m.AppType,
								  Domain = m.Domain,
								  MchID = m.MchID,
								  NotifyUrl = m.NotifyUrl,
								  SvrIP = m.SvrIP,
								  Sort = m.Sort
							  }).AsNoTracking().SingleOrDefault();
				if (result == null)
				{
					throw new BuzException("参数有误");
				}
				return result;
			}
			catch (ArgumentException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取对象信息出错");
				throw new BuzException("获取对象信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 删除参数
		/// </summary>
		/// <param name="id"></param>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public bool Delete(int id, UserSession sessionCurrent)
		{
			bool success = false;
			try
			{
				//if (logger.IsEnabled(LogLevel.Debug))
				//{
				//	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
				//}
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}

				using (var trans = context.Database.BeginTransaction())
				{
					try
					{
						#region 事务具体操作
						DateTime dtNow = DateTime.Now;
						string ip = GetRequestIP();

						var modelOld = Get(id, true);
						Delete(modelOld);

						serviceSysLog.Add(sessionCurrent, ip, $"删除模板消息日志信息，原信息：", modelOld, dtNow);
						#endregion

						trans.Commit();
					}
					catch (Exception ex)
					{
						trans.Rollback();
						throw ex.InnerException ?? ex;
					}
				}

				success = true;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "删除模板消息日志信息出错");
				throw new BuzException("删除模板消息日志信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
			return success;
		}

		/// <summary>
		/// 获取下拉列表
		/// </summary>
		/// <returns></returns>
		public List<WX_AppConfig> GetAllList(UserSession sessionCurrent)
		{
			try
			{
				if (sessionCurrent == null)
				{
					throw new BuzException("用户会话不能为空");
				}
				var lst = (from m in context.WXAppConfig
						   where m.OrgID == sessionCurrent.OrgID
						   select new WX_AppConfig()
						   {
							   ID = m.ID,
							   AppID = m.AppID,
							   AppName = m.AppName,
							   AppDesc = m.AppDesc,
							   AppType = m.AppType,
							   MchID = m.MchID
						   }).AsNoTracking().ToList();
				return lst;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, "获取配置信息出错");
				throw new BuzException("获取配置信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}
	}
}